﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Sunny.UI.Forms
{
    public partial class UIFormShadow : Form
    {
        public UIFormShadow()
        {
            InitializeComponent();
            SetStyles();
            FormBorderStyle = FormBorderStyle.None;
            ShowInTaskbar = false;
        }
        public int CornerRadius = 5;
        private int ShadowWidth = 8;
        private Form mainForm = null;
        public Form MainForm
        {
            get => mainForm;
            set
            {
                mainForm = value;
                Owner = mainForm;
            }
        }
        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            if (mainForm != null)  mainForm.Activate();
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (mainForm != null)
                DrawShadow();
        }
        private void SetStyles()
        {
            SetStyle(
                ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.ResizeRedraw |
                ControlStyles.DoubleBuffer, true);
            //强制分配样式重新应用到控件上
            UpdateStyles();
            base.AutoScaleMode = AutoScaleMode.None;
        }
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cParms = base.CreateParams;
                cParms.ExStyle |= 0x00080000; // WS_EX_LAYERED
                return cParms;
            }
        }
        internal void DrawShadow()
        {
            if (mainForm == null || mainForm.IsDisposed)
                return;

            Location = new Point(mainForm.Left - ShadowWidth, mainForm.Top - ShadowWidth);
            Size = new Size(mainForm.Width + 2 * ShadowWidth, mainForm.Height + 2 * ShadowWidth);

            Bitmap bitmap = null;
            Graphics g = null;
            try
            {
                bitmap = new Bitmap(Width, Height);
                g = Graphics.FromImage(bitmap);
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                int iMax = ShadowWidth - 1;
                
                for (int i = 0; i < ShadowWidth; i++)
                {
                    int ck = 200 * (iMax - i) / iMax;
                    Pen p = new Pen(Color.FromArgb((int)(40 * i / iMax), ck, ck, ck), 1.5F);
                    DrawRoundRectangle(g, p, new Rectangle(i, i, Width - (2 * i) - 1, Height - (2 * i) - 1), CornerRadius);
                    p.Dispose();
                }
                SetBits(bitmap);
            }
            catch { }
            finally
            {
                g?.Dispose();
                bitmap?.Dispose();
            }
        }
        public void SetBits(Bitmap bitmap)
        {
            if (!Image.IsCanonicalPixelFormat(bitmap.PixelFormat) || !Image.IsAlphaPixelFormat(bitmap.PixelFormat))
                throw new ApplicationException("图片必须是32位带Alhpa通道的图片。");
            IntPtr oldBits = IntPtr.Zero;
            IntPtr screenDC = UIFormWinHelper.GetDC(IntPtr.Zero);
            IntPtr hBitmap = IntPtr.Zero;
            IntPtr memDc = UIFormWinHelper.CreateCompatibleDC(screenDC);

            try
            {
                UIFormWinHelper.Point topLoc = new UIFormWinHelper.Point(Left, Top);
                UIFormWinHelper.Size bitMapSize = new UIFormWinHelper.Size(Width, Height);
                UIFormWinHelper.BLENDFUNCTION blendFunc = new UIFormWinHelper.BLENDFUNCTION();
                UIFormWinHelper.Point srcLoc = new UIFormWinHelper.Point(0, 0);

                hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                oldBits = UIFormWinHelper.SelectObject(memDc, hBitmap);

                blendFunc.BlendOp = UIFormWinHelper.AC_SRC_OVER;
                blendFunc.SourceConstantAlpha = Byte.Parse(((int)(MainForm.Opacity * 255)).ToString());
                blendFunc.AlphaFormat = UIFormWinHelper.AC_SRC_ALPHA;
                blendFunc.BlendFlags = 0;

                UIFormWinHelper.UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0, ref blendFunc, UIFormWinHelper.ULW_ALPHA);
            }
            finally
            {
                if (hBitmap != IntPtr.Zero)
                {
                    UIFormWinHelper.SelectObject(memDc, oldBits);
                    UIFormWinHelper.DeleteObject(hBitmap);
                }
                UIFormWinHelper.ReleaseDC(IntPtr.Zero, screenDC);
                UIFormWinHelper.DeleteDC(memDc);
            }
        }
        public static void DrawRoundRectangle(Graphics g, Pen pen, Rectangle rect, int cornerRadius)
        {
            using (GraphicsPath path = CreateRoundedRectanglePath(rect, cornerRadius))
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.InterpolationMode = InterpolationMode.HighQualityBilinear;
                g.DrawPath(pen, path);
            }
        }
        internal static GraphicsPath CreateRoundedRectanglePath(Rectangle rect, int cornerRadius)
        {
            GraphicsPath roundedRect = new GraphicsPath();
            roundedRect.AddArc(rect.X, rect.Y, cornerRadius * 2, cornerRadius * 2, 180, 90);
            roundedRect.AddLine(rect.X + cornerRadius, rect.Y, rect.Right - cornerRadius * 2, rect.Y);
            roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y, cornerRadius * 2, cornerRadius * 2, 270, 90);
            roundedRect.AddLine(rect.Right, rect.Y + cornerRadius * 2, rect.Right, rect.Y + rect.Height - cornerRadius * 2);
            roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y + rect.Height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90);
            roundedRect.AddLine(rect.Right - cornerRadius * 2, rect.Bottom, rect.X + cornerRadius * 2, rect.Bottom);
            roundedRect.AddArc(rect.X, rect.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90);
            roundedRect.AddLine(rect.X, rect.Bottom - cornerRadius * 2, rect.X, rect.Y + cornerRadius * 2);
            roundedRect.CloseFigure();
            return roundedRect;
        }

    }
}
